package jp.reflexworks.gdata.util;

import java.io.IOException;
import java.net.URL;
import java.util.logging.Logger;

import com.google.gdata.client.GoogleService.SessionExpiredException;
import com.google.gdata.client.spreadsheet.FeedURLFactory;
import com.google.gdata.client.spreadsheet.SpreadsheetQuery;
import com.google.gdata.client.spreadsheet.SpreadsheetService;
import com.google.gdata.util.AuthenticationException;
import com.google.gdata.util.ServiceException;
import com.google.gdata.data.spreadsheet.ListFeed;
import com.google.gdata.data.spreadsheet.SpreadsheetFeed;
import com.google.gdata.data.spreadsheet.SpreadsheetEntry;
import com.google.gdata.data.spreadsheet.WorksheetEntry;

public class SpreadsheetUtil {

	public static final String SPREADSHEET_URL = "http://spreadsheets.google.com/feeds/spreadsheets/";
	public static final String DOCS_DEFAULT_URL = "https://docs.google.com/feeds/default/private/full/";
	
	public static final int NUM_RETRIES = 5;
	public static final int SLEEP_MILL_SECOND = 200;

	public SpreadsheetService service;

	Logger logger = Logger.getLogger(this.getClass().getName());

	private String appName;
	private String email;
	private String password;
	
	public SpreadsheetUtil(String appName, String zEmail, String zPassword) {
		this.appName = appName;
		this.email = zEmail;
		this.password = zPassword;
	}

	public SpreadsheetService login() throws AuthenticationException {
		SpreadsheetService service = null;
		for (int r = 0; r < NUM_RETRIES; r++) {
			try {
				service = new SpreadsheetService(appName);
				service.setUserCredentials(email, password);
				this.service = service;
				return service;

			} catch (AuthenticationException e) {
				logger.info("AuthenticationException:"+e.getMessage());
				if (r == (NUM_RETRIES - 1)) {
					throw e;
				}
				sleep(SLEEP_MILL_SECOND);
			}
		}
		return null;
	}
	
	/*
	 * タイトルよりSpreadsheetのFeedを取得
	 */
	public SpreadsheetFeed getSpreadsheetFeed(String titleQuery) 
	throws ServiceException, IOException {
        FeedURLFactory urlFactory = FeedURLFactory.getDefault();
        SpreadsheetQuery spreadsheetQuery = new SpreadsheetQuery(urlFactory.getSpreadsheetsFeedUrl());
        spreadsheetQuery.setTitleQuery(titleQuery); // 検索対象のスプレッドシート名を指定している

        if (service == null) {
        	login();
        }
        for (int r = 0; r < NUM_RETRIES; r++) {
			try {
				return service.query(spreadsheetQuery, SpreadsheetFeed.class);

			} catch (IOException e) {
				logger.info("IOException:"+e.getMessage());
				if (r == (NUM_RETRIES - 1)) {
					throw e;
				}
				sleep(SLEEP_MILL_SECOND);

			} catch(SessionExpiredException e) {
				logger.info("SessionExpiredException:"+e.getMessage());
				login();

			} catch (ServiceException e) {
				logger.info("ServiceException:"+e.getMessage());
				if (r == (NUM_RETRIES - 1)) {
					throw e;
				}
				sleep(SLEEP_MILL_SECOND);
			}
		}
        return null;
	}
	
	/*
	 * タイトルよりSpreadsheetのFeedを取得し、最初のEntryを返却
	 * Entryが存在しない場合はnullを返す
	 */
	public SpreadsheetEntry getSpreadsheetEntry(String titleQuery)
	throws ServiceException, IOException {
		SpreadsheetFeed feed = getSpreadsheetFeed(titleQuery);
		if (feed != null && feed.getEntries().size() > 0) {
			feed.getEntries().get(0);
		}
		return null;
	}
	
	/*
	 * タイトルよりSpreadsheetのFeedを取得し、最初のEntryを取得し、デフォルトのワークシートを返却
	 * Entryが存在しない場合はnullを返す
	 */
	public WorksheetEntry getDefaultWorksheet(String titleQuery)
	throws ServiceException, IOException {
		SpreadsheetFeed feed = getSpreadsheetFeed(titleQuery);
		if (feed != null && feed.getEntries().size() > 0) {
			return feed.getEntries().get(0).getDefaultWorksheet();
		}
		return null;
	}
	
	/*
	 * ListFeedを取得
	 */
	public ListFeed getListFeed(WorksheetEntry worksheetEntry) 
	throws ServiceException, IOException {
		return getListFeed(worksheetEntry.getListFeedUrl());
	}
		
	/*
	 * ListFeedを取得
	 */
	public ListFeed getListFeed(URL listFeedUrl) 
	throws ServiceException, IOException {

        if (service == null) {
        	login();
        }
        for (int r = 0; r < NUM_RETRIES; r++) {
			try {
		        return service.getFeed(listFeedUrl, ListFeed.class);

			} catch (IOException e) {
				logger.info("IOException:"+e.getMessage());
				if (r == (NUM_RETRIES - 1)) {
					throw e;
				}
				sleep(SLEEP_MILL_SECOND);

			} catch(SessionExpiredException e) {
				logger.info("SessionExpiredException:"+e.getMessage());
				login();

			} catch (ServiceException e) {
				logger.info("ServiceException:"+e.getMessage());
				if (r == (NUM_RETRIES - 1)) {
					throw e;
				}
				sleep(SLEEP_MILL_SECOND);
			}
		}
        return null;
	}

	public synchronized void sleep(long msec) {
		try {
			wait(msec);
		} catch (InterruptedException e) {
		}
	}

}
